'''
Created on 2011-4-16

@author: Bob
'''
from jxgame.globals.GlobalDef import INVALID_CHAIR, GAME_GENRE_GOLD, US_PLAY
from jxgame.game.land.GameLogic import GameLogic, NORMAL_COUNT, FULL_COUNT,\
    ST_ORDER, CT_ERROR, CT_BOMB_CARD, CT_MISSILE_CARD
from jxgame.server.gameservice.TableFrame import TableFrame
from jxgame.globals.GlobalServerice import GameServiceOption, StartMode,\
    GER_DISMISS, GER_NORMAL, ScoreKind, ScoreInfo, GER_USER_LEFT
from jxgame.game.land.Cmd import GS_LAND_SCORE, GAME_PLAYER, SUB_S_SEND_CARD,\
    SUB_S_GAME_END, GS_LAND_FREE, GS_LAND_PLAYING, SUB_C_LAND_SCORE,\
    SUB_C_OUT_CART, SUB_C_PASS_CARD, SUB_C_TRUSTEE, SUB_C_USER_DOUBLE,\
    SUB_S_PASS_CARD, SUB_S_UserDouble, SUB_S_OUT_CARD, SUB_S_GAME_START,\
    SUB_S_LAND_SCORE
from random import randint
from twisted.test.test_adbapi import FirebirdConnector
from jxgame.proto.land_pb2 import CMD_S_SendAllCard, CMD_S_SendCard,\
    CMD_S_GameEnd, CMD_S_StatusFree, CMD_S_StatusScore, CMD_S_StatusPlay,\
    CMD_S_PassCard, CMD_S_UserDouble, CMD_S_OutCard, CMD_S_GameStart,\
    CMD_S_LandScore, CMD_C_LandScore, CMD_C_OutCard, CMD_C_UserTrustee,\
    CMD_C_UserDouble
from twisted.conch.manhole_tap import chainedProtocolFactory

GOOD_CARD_PERCENT       = 4                     #好牌概率

########################_#######################_#######################
class TableFrameSink:
    #游戏变量
    bomb_time           = 1
    land_score          = 0
    first_user          = 0
    bank_user           = INVALID_CHAIR
    current_user        = INVALID_CHAIR
    score_info          = []
    user_double         = []
    turn_index          = 0
    
    #运行信息
    turn_winer          = INVALID_CHAIR
    turn_card_count     = 0
    turn_card_data      = []
    user_trustee        = []
    
    #扑克信息
    back_card           = []
    card_count          = []
    out_card_count      = []
    hand_card_data      = []
    
    #组件变量
    game_logic          = None
    table_frame         = None
    server_option       = None
    
    #属性变量
    player_count        = GAME_PLAYER
    game_start_mode     = StartMode.StartMode_FullReady
    
    def __init__(self):
        self.game_logic = GameLogic()
        self.table_frame = TableFrame()
        self.server_option = GameServiceOption()
    
    def get_game_start_mode(self):
        return self.game_start_mode        
    
    def is_user_playing(self):
        return True
    
    def on_event_game_start(self):
        self.table_frame.game_status = GS_LAND_SCORE
        send_good_card = randint(0, GOOD_CARD_PERCENT)
        
        ai_user_count = 0
        ai_user = []
        self.turn_index = 0
        
        for i in range(GAME_PLAYER):
            server_user = self.table_frame.GetServerUserItem(i)
            if server_user.is_ai_user():
                ai_user[ai_user_count] = i
                ai_user_count += 1
            
            have_good_card_ai_user = INVALID_CHAIR
            if ai_user_count > 0:
                have_good_card_ai_user = ai_user[randint(ai_user_count)]
        if send_good_card == 1 and have_good_card_ai_user != INVALID_CHAIR:
            rand_card = self.game_logic.AllCardData
            self.game_logic.RandCardList(rand_card)
            
            good_card = []
            self.game_logic.GetGoodCardData(good_card)
            self.game_logic.RemoveGoodCardData(good_card, NORMAL_COUNT, rand_card , FULL_COUNT)
            #分发扑克
            self.hand_card_data[have_good_card_ai_user] = good_card
            self.card_count[have_good_card_ai_user] = NORMAL_COUNT
            j = 0
            for i in range(self.player_count):
                if i != have_good_card_ai_user:
                    self.card_count[i] = NORMAL_COUNT
                    self.hand_card_data[i] = rand_card[j*NORMAL_COUNT:(j+1)*NORMAL_COUNT]
                    j += 1
            self.back_card = rand_card[34:]
            self.game_logic.SortCardList(self.back_card, ST_ORDER)
        else:
            rand_card = self.game_logic.AllCardData
            self.game_logic.RandCardList(rand_card)
            for i in range(self.player_count):
                self.card_count[i] = NORMAL_COUNT
                self.hand_card_data[i] = rand_card[j*NORMAL_COUNT:(j+1)*NORMAL_COUNT]
            self.back_card = rand_card[51:]
            self.game_logic.SortCardList(self.back_card, ST_ORDER)
        
        self.current_user = randint(0,GAME_PLAYER)
        self.first_user = self.current_user
        
        cmd = CMD_S_SendAllCard()
        cmd.current_user = self.current_user
        
        cmd.card_data = self.hand_card_data
        cmd.back_card_data = self.back_card
        
        for i in range(self.player_count):
            cmd2 = CMD_S_SendCard()
            cmd2.current_user = self.current_user
            
            server_user = self.table_frame.GetServerUserItem(i)
            if server_user.is_ai_user:
                self.table_frame.SendTableData(i, SUB_S_SEND_CARD,cmd)
                self.table_frame.SendLookonData(i, SUB_S_SEND_CARD,cmd)
            else:
                cmd2.card_data = self.hand_card_data[i]
                self.table_frame.SendTableData(i, SUB_S_SEND_CARD,cmd2)
                self.table_frame.SendLookonData(i, SUB_S_SEND_CARD,cmd2)
            self.game_logic.SearchOutCard(self.hand_card_data[i])
        return True
                
    def on_event_game_end(self, chair_id, server_user, reason):
        assert server_user != None
        assert chair_id < self.player_count
        
        cmd = CMD_S_GameEnd()
        cmd.bomb_time = self.bomb_time
        cmd.land_score = self.land_score
        cmd.game_grade = self.server_option.cell_score
        #剩余扑克
        card_pos = 0
        for i in range(self.player_count):
            cmd.card_count[i] = self.card_count[i]
            cmd.card_data[card_pos] = self.hand_card_data[i]
            card_pos += cmd.card_count[i]
        if reason == GER_DISMISS: #游戏解散
            self.table_frame.SendTableData(INVALID_CHAIR, SUB_S_GAME_END, cmd)
            self.table_frame.SendLookonData(INVALID_CHAIR, SUB_S_GAME_END, cmd) 
            self.table_frame.ConcludeGame()
            return True
        elif reason == GER_NORMAL:
            cell_score = 1
            land_win = self.card_count[self.bank_user] == 0
            #春天判断
            user1 = (self.bank_user+1)%GAME_PLAYER
            user2 = (self.bank_user+2)%GAME_PLAYER
            if (self.out_card_count[user1]==0 and self.out_card_count[user2]==0):
                self.bomb_time *= 2
            else:
                if self.out_card_count[self.bank_user]==1:
                    self.bomb_time *= 2
            #炸弹限制            
            self.bomb_time = self.bomb_time if self.bomb_time<16 else 16
            #游戏积分
            score = 0
            tax = 0
            user_double = 0
            score_kind = ScoreKind.ScoreKind_Draw
            #统计积分
            for i in range(self.player_count):
                score = 0
                tax = 0
                user_double = 1
                if i == self.bank_user:
                    user_double1 = 0
                    #下家
                    if self.user_double[(i+1)%3] >0:
                        user_double1 += 2
                        if self.user_double[self.bank_user]>0:
                            user_double1 += 2
                        score = user_double1*self.bomb_time*self.land_score*cell_score*(1 if land_win else -1)
                    else:
                        score = self.bomb_time*self.land_score*cell_score*(1 if land_win else -1)
                    user_double1 = 0
                    #上家
                    if self.user_double[(i+2)%3] >0:
                        user_double1 += 2
                        if self.user_double[self.bank_user]>0:
                            user_double1 += 2
                        score = user_double1*self.bomb_time*self.land_score*cell_score*(1 if land_win else -1)
                    else:
                        score = self.bomb_time*self.land_score*cell_score*(1 if land_win else -1)
                    cmd.game_score[i] = score
                else:
                    if self.user_double[i]>0:
                        user_double *= 2
                        if self.user_double[self.bank_user]>0:
                            user_double *= 2
                    score = user_double*self.bomb_time*self.land_score*cell_score*(1 if land_win else -1)
                    cmd.game_score[i] = user_double*self.bomb_time*self.land_score*1*(1 if land_win else -1)                        
                
                score_kind = ScoreKind.ScoreKind_Win if cmd.game_score[i]>0 else ScoreKind.ScoreKind_Lost
                if self.server_option.server_type==GAME_GENRE_GOLD:
                    if cmd.game_score[i]>=100:
                        tax = 0
                        score -= tax
                        cmd.game_score[i]=cmd.game_score[i]-tax
                #修改分数
                score_info = ScoreInfo()
                score_info.RankPoint = score
                if self.server_option.cell_score>0:
                    score_info.UBiMoney = score_info.RankPoint*self.server_option.cell_score
                    score_info.UBiRevenue = (1 if score_info.UBiMoney>0 else 0)*score_info.UBiMoney*self.server_option.tax/100 #U币*税收
                    score_info.ScoreKind = score_kind
                    score_info.UBiMoney -= score_info.UBiRevenue
                else: #中国移动模式
                    score_info.UBiMoney = 0
                    score_info.UBiRevenue = 0
                    score_info.ScoreKind = score_kind
                #积分,U币    
                cmd.game_score[i] = score
                cmd.ubi[i] = score_info.UBiMoney
            #发送信息
            self.table_frame.SendTableData(INVALID_CHAIR,SUB_S_GAME_END,cmd)
            self.table_frame.SendLookonData(INVALID_CHAIR,SUB_S_GAME_END,cmd)
            #切换用户
            self.first_user = chair_id
            self.table_frame.ConcludeGame()
            return True
        elif reason == GER_USER_LEFT:
            #统计未出的炸弹
            not_out_bomb_count = 0
            if self.server_option.cell_score<=0: #中国移动模式
                #TODO:未实现
                pass
            self.bomb_time = min([self.bomb_time,16])
            self.land_score = max([self.land_score,1])
        pass
    
    def send_game_scene(self, chair_id, server_user, game_status,send_sceret):
        if game_status == GS_LAND_FREE:
            cmd = CMD_S_StatusFree()
            cmd.base_score=self.server_option.cell_score
            return self.table_frame.SendGameScene(server_user,cmd)
        elif game_status == GS_LAND_SCORE:
            cmd = CMD_S_StatusScore()
            cmd.land_score=self.land_score
            cmd.current_user = self.current_user
            cmd.base_score = self.server_option.cell_score
            cmd.score_info = self.score_info
            cmd.card_data = self.hand_card_data
            cmd.user_trustee = self.user_trustee
            return self.table_frame.SendGameScene(server_user,cmd)
        elif game_status == GS_LAND_PLAYING:
            cmd = CMD_S_StatusPlay()
            cmd.bomb_time = self.bomb_time
            cmd.land_user = self.bank_user
            cmd.current_user = self.current_user
            cmd.last_out_user = self.turn_winer
            cmd.land_score = self.land_score
            cmd.turn_card_count = self.turn_card_count
            cmd.back_card = self.back_card
            cmd.card_count = self.card_count
            cmd.turn_card_data = self.turn_card_data
            cmd.card_data = self.hand_card_data
            cmd.user_trustee = self.user_trustee
            return self.table_frame.SendGameScene(server_user,cmd)
        return False
    
    def on_timer_message(self, time_id, param):
        return  False
    
    def on_game_message(self, sub_cmd_id, data_buf,server_user):
        user_data = server_user.user_data
        if sub_cmd_id == SUB_C_LAND_SCORE:
            if user_data.user_status!=US_PLAY: return True
            cmd = CMD_C_LandScore()
            return self.on_user_land_score(user_data.chaire_id, cmd.land_score)
        elif sub_cmd_id == SUB_C_OUT_CART:
            if user_data.user_status!=US_PLAY: return True
            cmd = CMD_C_OutCard()
            return self.on_user_out_card(user_data.chaire_id, cmd.card_count)
        elif sub_cmd_id == SUB_C_PASS_CARD:
            if user_data.user_status!=US_PLAY: return True
            return self.on_user_pass_card(user_data.chaire_id)
        elif sub_cmd_id == SUB_C_TRUSTEE:
            cmd = CMD_C_UserTrustee()
            self.user_trustee[cmd.user_chair_id] = cmd.trustee
            self.table_frame.SendTableData(INVALID_CHAIR,SUB_C_TRUSTEE,cmd)
            self.table_frame.SendLookonData(INVALID_CHAIR,SUB_C_TRUSTEE,cmd)
            return True
        elif sub_cmd_id == SUB_C_USER_DOUBLE:
            if user_data.user_status!=US_PLAY: return True
            cmd = CMD_C_UserDouble()
            return self.on_user_double(cmd.chair_id, cmd.double)
        return True    
    def on_frame_message(self):
        return False
    
    def on_user_land_score(self,chair_id,land_score):
        if self.table_frame.game_status!=GS_LAND_SCORE: return True
        if chair_id!=self.current_user: return False
        if (land_score>3 and land_score!=255) or land_score<=self.land_score: return False
        
        if land_score!=255:
            self.land_score=land_score
            self.bank_user=self.current_user
        self.score_info[chair_id]=land_score
        #开始判断
        if self.land_score==3 or self.first_user==(chair_id+1)%self.player_count:
            #重新发牌
            if self.land_score==0: return self.on_event_game_start()
            #设置变量
            if self.bank_user==INVALID_CHAIR: self.bank_user=self.first_user
            #设置状态
            self.table_frame.game_status=GS_LAND_PLAYING
            #发送底牌
            self.card_count[self.bank_user]=20
            self.hand_card_data[self.bank_user].extend(self.back_card)
            self.game_logic.SortCardList(self.hand_card_data[self.bank_user], ST_ORDER)
            #出牌信息
            self.turn_card_count=0
            self.turn_winer=self.bank_user
            self.current_user=self.bank_user
            self.turn_index=0
            
            #发送消息
            cmd = CMD_S_GameStart()
            cmd.land_user=self.bank_user
            cmd.land_score=self.land_score
            cmd.current_user=self.current_user
            cmd.score_info = self.score_info
            cmd.back_card=self.back_card
            cmd.game_mode=0 if self.server_option.cell_score>0 else 1
            
            self.table_frame.SendTableData(INVALID_CHAIR,SUB_S_GAME_START,cmd)
            self.table_frame.SendLookonData(INVALID_CHAIR,SUB_S_GAME_START,cmd)
            return True
        #设置用户
        self.current_user=(chair_id+1)%self.player_count
        #发送消息
        cmd = CMD_S_LandScore()
        cmd.land_user = chair_id
        cmd.land_score = land_score
        cmd.current_user= self.current_user
        cmd.current_score=self.land_score
        self.table_frame.SendTableData(INVALID_CHAIR,SUB_S_LAND_SCORE,cmd)
        self.table_frame.SendLookonData(INVALID_CHAIR,SUB_S_LAND_SCORE,cmd)
        return True
    
    def on_user_out_card(self,chair_id, card_data):
        if self.table_frame.game_status!=GS_LAND_PLAYING: return True
        if chair_id!=self.current_user: return False
        card_count = len(card_data)
        #计算轮数
        if (chair_id+1)%3==self.bank_user: self.turn_index+=1
        #排序扑克
        self.game_logic.SortCardList(card_data, ST_ORDER)
        card_type=self.game_logic.GetCardType(card_data)
        if card_type==CT_ERROR: return False
        
        #更随出牌
        if self.turn_card_count==0: self.turn_card_count=card_count
        elif not self.game_logic.CompareCard(self.turn_card_data, card_data):return False
        
        #删除扑克
        if not self.game_logic.RemoveCard(card_data, self.hand_card_data[chair_id]): return False
        self.card_count[chair_id] -= card_count
        
        #出牌记录
        self.turn_card_count=card_count
        self.out_card_count[chair_id]+=1
        self.turn_card_data = card_data
        #炸弹判断
        if card_type==CT_BOMB_CARD or card_data==CT_MISSILE_CARD: self.bomb_time*=2
        #切换用户
        self.turn_winer=chair_id
        if self.card_count[chair_id]!=0:
            if card_type!=CT_MISSILE_CARD: self.current_user=(self.current_user+1)%self.player_count
        else: self.current_user=INVALID_CHAIR
        
        cmd = CMD_S_OutCard()
        cmd.card_count=card_count
        cmd.out_card_user=chair_id
        cmd.current_user=self.current_user
        cmd.turn_index=self.turn_index
        cmd.card_data=self.turn_card_data
        self.table_frame.SendTableData(INVALID_CHAIR,SUB_S_OUT_CARD,cmd)
        self.table_frame.SendLookonData(INVALID_CHAIR,SUB_S_OUT_CARD,cmd)
        #出牌最大
        if card_type==CT_MISSILE_CARD: self.turn_card_count=0
        if self.current_user==INVALID_CHAIR: self.on_event_game_end(chair_id, None, GER_NORMAL)
        return True

    def on_user_pass_card(self, chair_id):
        if self.table_frame.game_status != GS_LAND_PLAYING: return True
        if (chair_id!=self.current_user) or (self.turn_card_count==0): return False
        #计算轮数
        if (chair_id+1)%3 == self.bank_user: self.turn_index += 1
        
        self.current_user = (self.current_user+1)%self.player_count
        if self.current_user==self.turn_winer: self.turn_card_count =0
        
        cmd = CMD_S_PassCard()
        cmd.pass_user = chair_id
        cmd.current_user = self.current_user
        cmd.turn_index = self.turn_index
        cmd.new_turn = self.turn_card_count==0
        self.table_frame.SendTableData(INVALID_CHAIR,SUB_S_PASS_CARD,cmd)
        self.table_frame.SendLookonData(INVALID_CHAIR,SUB_S_PASS_CARD,cmd)
    
    def on_user_double(self, chair_id, double):
        if self.table_frame.game_status != GS_LAND_PLAYING: return False
        cmd = CMD_S_UserDouble()
        cmd.land_user = chair_id
        cmd.land_double = double
        cmd.current_user = 255
        cmd.current_user2 = 255
        cmd.state = 1
        #农民第一轮 倒
        if (chair_id!=self.bank_user) and (self.score_info[chair_id]==0) and self.turn_index<1 and self.user_double[chair_id]==0:
            next_chair_id = (chair_id+1)%self.player_count
            if next_chair_id==self.bank_user: #地主
                if self.user_double[(self.bank_user+1)%3]==1:
                    self.user_double[chair_id]=2
                    cmd.state=-1
                elif self.user_double[(self.bank_user+1)%3]==2:
                    self.user_double[chair_id]=1
                    cmd.state=-1
                else:
                    cmd.current_user=(self.bank_user+1)%3
                    self.user_double[chair_id]=1                    
            else:
                if self.user_double[next_chair_id]==1:
                    self.user_double[chair_id]=2
                    cmd.state=-1
                elif self.user_double[next_chair_id]==2:
                    self.user_double[chair_id]=1
                    cmd.state=-1
                else:
                    self.user_double[chair_id]=1                    
                    cmd.current_user=(next_chair_id)%3
            cmd.land_double = self.user_double[chair_id]
            cmd.current_user2 = self.bank_user
        #农民第一轮 跟
        elif chair_id!=self.bank_user and double==2 and self.user_double[chair_id]==0 and self.turn_index<1:
            self.user_double[chair_id]=double
            cmd.current_user=self.bank_user
            cmd.current_user2=255
        #庄 反
        elif chair_id==self.bank_user and (self.user_double[(chair_id+2)%3]!=0 or self.user_double[(chair_id+1)%3]!=0 and self.turn_index<2):
            self.user_double[chair_id]=double
        self.table_frame.SendTableData(INVALID_CHAIR,SUB_S_UserDouble,cmd)
        self.table_frame.SendLookonData(INVALID_CHAIR,SUB_S_UserDouble,cmd)
        return True
    